<?php
namespace App\Common\Cla\EChat\Server;

use App\Common as com;
use App\Common\Cla\EChat\Server\ReceivePools as thisReceivePools;

class ReceivePools extends com\Cla\ClaBase {


	/**
	 * 接收池
	 * @var thisReceivePools\Item[]
	 */
	private array $receivePools = [];

	/**
	 * 接收池id
	 * @var int
	 */
	private int $receivePoolsIndex = 0;


	/**
	 * 接收池
	 * @var array
	 */
	private array $receivePoolsIndexOfChannelRoomSid = [];

	public function __construct(  ) {
		parent::__construct();
	}

	/**
	 * 获取接收通道类
	 * @param int $receiveId
	 * @return ReceivePools\Item|null
	 */
	public function getReceiveItem( int $receiveId ):thisReceivePools\Item|null {
		return $this->receivePools[ $receiveId ] ?? null;
	}

	/**
	 * @param string $channelSid
	 * @param string $roomSid
	 * @param \Closure $callback
	 * @param int|null $receiveTimeoutS 接收超时（单位：秒） [null]默认超时 [-1][默认]不超时
	 * @return int 返回接收id
	 */
	public function add( string $channelSid, string $roomSid, \Closure $msgCallback, \Closure $stopCallback, ?int $receiveTimeoutS = -1 ):int {
		$receiveId = ++$this->receivePoolsIndex;
		//
		$this->receivePools[ $receiveId ] = thisReceivePools\Item::makeOfNew( $receiveId, $channelSid, $roomSid, $msgCallback, $stopCallback, $receiveTimeoutS );
		//
		// 初始化
		if( ! array_key_exists( $channelSid, $this->receivePoolsIndexOfChannelRoomSid ) ){
			$this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] = [];
		}
		if( ! array_key_exists( $roomSid, $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] ) ){
			$this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] = [];
		}
		// 设置roomSid索引
		$this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ][] = $receiveId;
		//
		return $receiveId;
	}

	/**
	 * 是否存在
	 * @param int $receiveId
	 * @return bool
	 */
	public function has( int $receiveId ):bool {
		return array_key_exists( $receiveId, $this->receivePools );
	}

	/**
	 * @param int $receiveId
	 * @param int|null $waitTimeoutS 等待超时时间。单位：秒
	 * @return bool 是否已结束 [true]正常结束 [fasle]超时或已关闭
	 */
	public function waitReceive( int $receiveId, ?int $waitTimeoutS = null ):bool {
		if( ! $this->has( $receiveId ) ){
			// 不存在
			return false;
		}
		return $this->receivePools[ $receiveId ]->waitReceive( $waitTimeoutS );
	}

	/**
	 * 删除指定回调
	 * @param int $receiveId
	 * @return bool 是否已结束 [true]正常结束 [fasle]超时或已关闭
	 */
	public function rm( int $receiveId ):bool {
		if( ! $this->has( $receiveId ) ){
			return true;
		}
		// 删除索引表
		$channelSid = $this->receivePools[ $receiveId ]->getChannelSid();
		$roomSid = $this->receivePools[ $receiveId ]->getRoomSid();
		//
		if( array_key_exists( $channelSid, $this->receivePoolsIndexOfChannelRoomSid ) ){
			if( array_key_exists( $roomSid, $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] ) ){
				$receivePoolsIndexOfRoomSidSite = array_search( $receiveId, $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] );
				if( $receivePoolsIndexOfRoomSidSite !== false ){
					unset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ][ $receivePoolsIndexOfRoomSidSite ] );
				}
				// 如果roomSid集合成员数为0，则删除整个集合
				if( empty( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] ) ){
					unset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] );
				}
			}
			// 如果channelSid集合成员数为0，则删除整个集合
			if( empty( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] ) ){
				unset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] );
			}
		}
		// 检查房间是否已清空
		if( ! isset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] ) ){
			// 调用结束接收回调
			$this->receivePools[ $receiveId ]->callStopCallback();
		}
		// 删除主表
		unset( $this->receivePools[ $receiveId ] );
		//
		return true;
	}

	/**
	 * 清理垃圾数据
	 * @return $this
	 * @throws com\Lib\Err\BaseException\Throw_
	 */
	private function cg(  ):self {
		// throw com\Lib\Err\Exception::makeOfNew( '未做', com\Lib\Err\Code::$sysAssertError );
		/*
		foreach( $this->receivePoolsIndexOfChannelRoomSid as $channelSid => $channel ){
			// 清理房间
			foreach( $channel as $roomSid => $room ){
				if(  count( $room ) === 0 ){
					unset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] );
				}
			}
			// 清理通道
			if(  count( $channel ) === 0 ){
				unset( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ] );
				// 关闭接收器

			}
		}
		*/
		//
		return $this;
	}

	/**
	 * @param string $channelSid
	 * @param string $roomSid
	 * @return thisReceivePools\Item[]
	 */
	public function getPoolsOfChannelRoomSid( string $channelSid, string $roomSid ):array {
		$pools = [];
		foreach( $this->receivePoolsIndexOfChannelRoomSid[ $channelSid ][ $roomSid ] ?? [] as $receivePoolsIndex ){
			if( array_key_exists( $receivePoolsIndex, $this->receivePools ) ){
				$pools[] = $this->receivePools[ $receivePoolsIndex ];
			}
		}
		return $pools;
	}

	public function callReceiveOfRoomSid( string $channelSid, string $roomSid, \PhpAmqpLib\Message\AMQPMessage $AMQPMsg ):int {
		// $isExistErr = false;
		$callNum = 0;
/*		foreach( $this->receivePools as $receivePoolValue ){
			d([
				'AAA',
				$receivePoolValue->getRoomSid(),
			]);
		}*/
		foreach( $this->getPoolsOfChannelRoomSid( $channelSid, $roomSid ) as $receivePoolValue ){
			if( $receivePoolValue->callReceive( $AMQPMsg ) ){
				$callNum++;
			}else{
				// $isExistErr = true;
			}
		}
		// 有不存在数据时进行一次cg
		/*
		if( $isExistErr ){
			$this->cg();
		}
		*/
		//
		return $callNum;
	}

	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * @return $this
	 */
	public static function makeOfNew():self {
	    return self::make();
	}

}
